<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/4/20
 * Time: 10:38
 */
require_once '../../conn.php';

class ChatManager
{
    private $redis_client;
    private $key_roomid_fd = 'set.richesmeapp_roomid:';//记录每个房间里都有哪些人的 a:房间id {1,3,4,5,6,7,8}
    private $key_fd_roomid = 'hset.richesmeapp_fd_roomid';//记录每个用户都进入了哪些房间
    private $key_room_config = 'hset.richesmeapp_room_config_roomid:';//记录房间的设置
    private $key_room_record_list = 'list.richesmeapp_room_record_list_roomid:';//记录不同房间的最新20条数据
    private $key_room_banned_user_list = 'hset.richesmeapp_room_banned_user_list_roomid:';//记录不同房间的禁言用户
    private $key_all_room_list = 'set.richesmeapp_all_room_list';//所有房间列表
    private $key_all_room_sum_see_people = 'set.richesmeapp_room_sum_see_peopl:roomid:';//每个房间人累计观看人数

    public function __construct()
    {
        global $redis_db;
        $this->redis_client = new Predis\Client();
        $this->redis_client->select($redis_db);//测试版用数据库0 正式版用数据库1
    }

    /**
     * 获得房间的累计观看次数
     * @param $room_id
     * @return int
     */
    public function getRoomSumPeople($room_id)
    {
        if ($this->redis_client->exists($this->key_all_room_sum_see_people . $room_id)) {
            $num=(int)$this->redis_client->incr($this->key_all_room_sum_see_people . $room_id);
        }else{
            $num=$this->redis_client->append($this->key_all_room_sum_see_people . $room_id,1);
        }
        return $num;
    }

    /**
     * 获得房间实时观看人数
     * @param $room_id
     * @return int
     */
    public function getRoomNowPeople($room_id)
    {
        $watch_num=$this->redis_client->scard($this->key_roomid_fd.$room_id)??0;
        return $watch_num;
    }

    /**
     * 获得该房间的所有禁言用户 id
     * @param $room_id
     * @return array
     */
    public function getBannedUser($room_id)
    {
        $user_list=$this->redis_client->hkeys($this->key_room_banned_user_list . $room_id);//禁言
        $banned_user_list = array();
        foreach ($user_list as $item) {
            $banned=$this->redis_client->hget($this->key_room_banned_user_list . $room_id,$item);//禁言
            if($banned==1&&$item!=0){
                $banned_user_list[] = $item;
            }
        }
        return $banned_user_list;
    }

    /**
     * 加入房间
     */
    public function joinChatRoom($fd, $roomid)
    {
        echo '来了';
        $this->createRoom($roomid);
        echo "进入房间" . PHP_EOL;
        //增加观看人数
        if ($this->redis_client->exists($this->key_all_room_sum_see_people . $roomid)) {
            $this->redis_client->incr($this->key_all_room_sum_see_people . $roomid);
        }else{
            $this->redis_client->append($this->key_all_room_sum_see_people . $roomid,1);
        }
        //hset
        // k-v : websocket连接id $fd  -  房间id
        $this->redis_client->hset($this->key_fd_roomid, $fd, $roomid);
        //set 判断房间id是否存在，否则创建，把fd加入
        $this->redis_client->sadd($this->key_roomid_fd . $roomid, $fd);
        echo "用户和房间id管理========fd：{$fd},chat_room_id:{$roomid}" . PHP_EOL;
        var_dump($this->redis_client->hgetall($this->key_fd_roomid));
        echo "房间管理=======chat_room_id:{$roomid},fd:{$fd}" . PHP_EOL;
        var_dump($this->redis_client->smembers($this->key_roomid_fd . $roomid));
    }

    /**
     * 创建房间
     * @param $room_id
     */
    public function createRoom($room_id)
    {
        $this->redis_client->sadd($this->key_all_room_list, $room_id);
    }

    /**
     * 退出房间
     */
    public function outChatRoom($fd)
    {
        //hset
        // k-v : websocket连接id $fd  -  房间id
        $room_id = $this->redis_client->hget($this->key_fd_roomid, $fd);
        $this->redis_client->hdel($this->key_fd_roomid, [$fd]);
        //拿到房间id 到对对应的房间id里面把这个链接id删掉
        $this->redis_client->srem($this->key_roomid_fd . $room_id, $fd);


        echo '退出房间：' . PHP_EOL;
        echo "用户和房间id管理========fd：{$fd},chat_room_id:{$room_id}" . PHP_EOL;
        var_dump($this->redis_client->hgetall($this->key_fd_roomid));
        echo "房间管理=======chat_room_id:{$room_id},fd:{$fd}" . PHP_EOL;
        var_dump($this->redis_client->scard($this->key_roomid_fd . $room_id));
        $res['watch_num']=$this->getRoomNowPeople($room_id);//返回在线人数
        $res['sum_watch_num']=$this->getRoomSumPeople($room_id);//返回在线人数
        $res['chat_room_id'] = $room_id;
        $res['type'] = 'exit_the_room';
        return $res;
    }

    /**
     * 根据roomid 返回这个房间的所有连接fd
     * @param $room_id
     * @return array|int
     */
    public function getRoomidFd($room_id)
    {
        $res = $this->redis_client->smembers($this->key_roomid_fd . $room_id);
//        var_dump($res);
        return $res;
    }

    /**
     * 过滤数据
     * @param string $data
     * @param $fd
     * @return string
     */
    public function filtraMessage(string $data, $fd): string
    {
        $res = (array)(json_decode($data));
        echo "收到消息：" . PHP_EOL;
        var_dump($res);
        if (isset($res['type'])) {
            $res['send_fd'] = $fd;
            switch ($res['type']) {
                case 'chat'://聊天
                    global $db, $tablepre;
                    $res['wtime']=time();
                    //记录聊天记录到数据库
                    $db->setCharset('utf8mb4');
                    $sql = parseArrToSql($tablepre, 'live_record_co', [
                        'chat_room_id' => $res['chat_room_id'],
                        'record_id' => '0',
                        'user_id' => $res['user_id'],
                        'username' => $res['username'],
                        'img_sl' => $res['img_sl'],
                        'content' => $res['content'],
                        'm_type' => $res['m_type'],
                        'm_type_id' => $res['m_type_id'],
                        'pass' => (int)($res['pass']??0),
                        'wtime' => time(),
                    ]);
                    $db->execute($sql);
                    $last_insert_id = $db->insert_id();
                    $res['msg_record_id'] = $last_insert_id;
                    //开启审核
                        // redis  把最新一条数据缓存到该房间的最新20条
                        $tmp_rg = getOneRowDataFromDatabase('live_record_co', '*,id as msg_record_id', "id='{$res['msg_record_id']}'")['data'] ?? false;
                        if ($tmp_rg) {
                            $tmp_dd = json_encode($tmp_rg, JSON_UNESCAPED_UNICODE);
                            $len = $this->redis_client->rpush($this->key_room_record_list . $res['chat_room_id'], [$tmp_dd]);
                            if ($len > 20) {
                                $this->redis_client->ltrim($this->key_room_record_list . $res['chat_room_id'], -20, -1);
                            }
                        }

                    $res['watch_num']=$this->getRoomNowPeople($res['chat_room_id']);
                    $res['sum_watch_num']=$this->getRoomSumPeople($res['chat_room_id']);
                    return json_encode($res, JSON_UNESCAPED_UNICODE);
                    break;
                case 'join'://初始化 进入群聊房间
                    $this->joinChatRoom($fd, $res['chat_room_id']);
                    //获得房间配置
                    $open_chat=$this->redis_client->hget($this->key_room_config . $res['chat_room_id'], 'open_chat')??1;
                    $need_audit=$this->redis_client->hget($this->key_room_config . $res['chat_room_id'], 'need_audit')??0;
                    $banned=(int)$this->redis_client->hget($this->key_room_banned_user_list . $res['chat_room_id'], $res['user_id']);//禁言
                    //返回这个房间的配置
                    $room_config['type'] = 'join';
                    $room_config['send_fd'] = $fd;
                    $room_config['chat_room_id'] = $res['chat_room_id'];
                    $room_config['open_chat'] = $open_chat;
                    $room_config['need_audit'] = $need_audit;
                    $room_config['m_type'] = $res['m_type'];
                    $room_config['m_type_id'] = $res['m_type_id'];
                    $room_config['user_id'] = $res['user_id'];
                    $room_config['watch_num'] =$this->getRoomNowPeople($res['chat_room_id']);
                    $room_config['sum_watch_num'] =$this->getRoomSumPeople($res['chat_room_id']);
                    $room_config['live_status'] = $this->redis_client->hget($this->key_room_config . $res['chat_room_id'], 'live_status')??'live_notstart';//播放状态



                    $room_config['banned'] =$banned;
                    //获得这个房间的群聊信息 最新20条
//                    $chat_room_msg_list = getMoreRowDataFromDatabase('live_record_co', '*,id as msg_record_id', "chat_room_id='{$res['chat_room_id']}'", 'id desc')['data'] ?? [];
                    $chat_room_msg_list = $this->redis_client->lrange($this->key_room_record_list . $res['chat_room_id'], 0, -1);
                    $list = array();
                    if(count($chat_room_msg_list)<1){
                        $chat_room_msg_list = getMoreRowDataFromDatabase('live_record_co', '*,id as msg_record_id', "chat_room_id='{$res['chat_room_id']}' and pass=1", 'id desc')['data'] ?? [];
                        //根据字段last_name对数组$data进行升序排列 **
                        $last_names = array_column($chat_room_msg_list,'id');
                        array_multisort($last_names,SORT_ASC,$chat_room_msg_list);

                        foreach ($chat_room_msg_list as $item) {
                            $list[] = $item;
                            $tmp_dd = json_encode($item, JSON_UNESCAPED_UNICODE);
                            $len=$this->redis_client->rpush($this->key_room_record_list . $res['chat_room_id'], [$tmp_dd]);
                        }
                    }else {
                        foreach ($chat_room_msg_list as $item) {
                            $list[] = json_decode($item, JSON_UNESCAPED_UNICODE);
                        }
                    }

                    $room_config['chat_room_msg_list'] = $list;
                    echo 'list:leng';
                    var_dump(count($list));
                    return json_encode($room_config, JSON_UNESCAPED_UNICODE);
                    break;
                case 'config':// 修改房间配置
                    //判断redis 缓存是否存在
                    $exit = getOneRowDataFromDatabase('live_chatroom_config_co', 'id', "chat_room_id='{$res['chat_room_id']}'")['data'] ?? false;
                    global $db, $tablepre;
                    if (!$exit) {
                        $sql = parseArrToSql($tablepre, 'live_chatroom_config_co', [
                            'chat_room_id' => $res['chat_room_id'],
                            'open_chat' => $res['open_chat'],
                            'need_audit' => $res['need_audit'],
                            'm_type' => $res['m_type'],
                            'm_type_id' => $res['m_type_id'],
                            'wtime' => time(),
                        ]);
                    } else {
                        $sql = parseArrToSql($tablepre, 'live_chatroom_config_co', [
                            'open_chat' => $res['open_chat'],
                            'need_audit' => $res['need_audit'],
                            'wtime' => time(),
                            'live_status' => $res['live_status'],
                        ], "chat_room_id='{$res['chat_room_id']}'", 'update');
                    }
                    $this->redis_client->hset($this->key_room_config . $res['chat_room_id'], 'open_chat', $res['open_chat']);
                    $this->redis_client->hset($this->key_room_config . $res['chat_room_id'], 'need_audit', $res['need_audit']);
                    $this->redis_client->hset($this->key_room_config . $res['chat_room_id'], 'live_status', $res['live_status']);//修改直播状态
                    $db->execute($sql);
                    return json_encode($res, JSON_UNESCAPED_UNICODE);
                    break;
                case 'chat_one_pass_status'://通过 允许可见 pass 1  0

                    global $db, $tablepre;
                    $msg_record_id = $res['msg_record_id'];
                    $sql=parseArrToSql($tablepre, 'live_record_co', ['pass' => (int)$res['pass']], "id={$msg_record_id}", 'update');
                    $db->execute($sql);
                    $this->updateRedisRoom20($res['chat_room_id']);
                    $msg_info=getOneRowDataFromDatabase('live_record_co', '*', "id={$msg_record_id}")['data'] ??[];
                    $res['username'] = $msg_info['username'] ?? '';
                    $res['img_sl'] = $msg_info['img_sl'] ?? '';
                    $res['content'] = $msg_info['content'] ?? '';
                    $res['user_id'] = $msg_info['user_id'] ?? '';
                    $res['pass'] = $msg_info['pass'] ?? '';
                    $res['wtime'] = $msg_info['wtime'] ?? '';
                    return json_encode($res, JSON_UNESCAPED_UNICODE);
                    break;
                case 'chat_user_banned'://用户禁言 取消
//                    $key_room_banned_user_list
                    $this->redis_client->hset($this->key_room_banned_user_list . $res['chat_room_id'], $res['user_id'], $res['banned']);
                    return json_encode($res, JSON_UNESCAPED_UNICODE);
                    break;
                case 'chat_one_delete'://用户某条发言删除
                    global $db, $tablepre;

                    $sql = "delete from live_record_co where id={$res['msg_record_id']}";
                    $db->execute($sql);
                    $this->updateRedisRoom20($res['chat_room_id']);
                    return json_encode($res, JSON_UNESCAPED_UNICODE);
                    break;
                case 'heartbeat_bag'://心跳包

                    return json_encode($res, JSON_UNESCAPED_UNICODE);
                    break;
            }
        }
        $res['type'] = 'not_type_';//没有type，填充的
        return json_encode($res, JSON_UNESCAPED_UNICODE);;
    }

    /**
     * 更新房间的前20条数据  1
     * @param $chat_room_id
     */
    public function updateRedisRoom20($chat_room_id)
    {
        $chat_room_msg_list = getMoreRowDataFromDatabase('live_record_co', '*,id as msg_record_id', "chat_room_id='{$chat_room_id}' and pass=1", 'id desc')['data'] ?? [];

        //根据字段last_name对数组$data进行升序排列 **
        $last_names = array_column($chat_room_msg_list,'id');
        array_multisort($last_names,SORT_ASC,$chat_room_msg_list);
        foreach ($chat_room_msg_list as $item) {
            $list[] = $item;
            $tmp_dd = json_encode($item, JSON_UNESCAPED_UNICODE);
            $len=$this->redis_client->rpush($this->key_room_record_list . $chat_room_id, [$tmp_dd]);
            if($len>20) {
                $this->redis_client->ltrim($this->key_room_record_list . $chat_room_id, -20, -1);
            }
        }
    }

    /**
     * 返回房间的聊天历史记录
     * @param string $chat_room_id 房间id
     * @param int $msg_record_id 最旧的记录id
     * @return array
     */
    public function getMsgRecordList(string $chat_room_id,int $msg_record_id)
    {
        $chat_room_msg_list=getMoreRowDataFromDatabase('live_record_co', '*,id as msg_record_id', "id<{$msg_record_id} and chat_room_id='{$chat_room_id}' and pass=1", 'id desc','limit 0,2')['data']??[];
        if($chat_room_msg_list) {
            //根据字段last_name对数组$data进行升序排列 **
            $last_names = array_column($chat_room_msg_list, 'id');
            array_multisort($last_names, SORT_ASC, $chat_room_msg_list);
        }
        return $chat_room_msg_list;
    }

}